// collect 包是链表，栈，队列的一些简单实现
// Example:
//
//	func main() {
//		var list collect.List[int]
//		list.Add(10)
//		fmt.Println(list.ToArray())
//	}
package collect

type node[T any] struct {
	data T
	next *node[T]
}

type List[T any] struct {
	head *node[T]
	end  *node[T]
	len  int
}

// Add 方法用来在链表末尾增加一个元素
func (l *List[T]) Add(data T) {
	newNode := &node[T]{
		data: data,
	}
	defer func() {
		l.len++
	}()

	if l.head == nil {
		l.head = newNode
		l.end = l.head
		return
	}

	l.end.next = newNode
	l.end = newNode
}

// Insert 方法在idx前插入一个元素
func (l *List[T]) Insert(idx int, data T) {
	if idx < 0 || idx > l.len {
		panic("访问越界")
	}

	newNode := &node[T]{
		data: data,
	}
	defer func() {
		l.len++
	}()

	if idx == 0 && l.len > 0 {
		newNode.next = l.head
		l.head = newNode
		return
	} else if idx == 0 && l.len == 0 {
		l.head = newNode
		l.end = l.head
		return
	} else if idx == l.len {
		l.end.next = newNode
		l.end = newNode
		return
	}

	ptr := l.head
	for i := 0; i < idx-1; i++ {
		ptr = ptr.next
	}

	newNode.next = ptr.next
	ptr.next = newNode
}

// Delete 方法删除idx处的元素
func (l *List[T]) Delete(idx int) {
	if idx < 0 || idx > l.len {
		panic("访问越界")
	}

	l.len--
	if idx == 0 && l.len > 0 {
		l.head = l.head.next
		return
	} else if idx == 0 && l.len == 0 {
		l.head = nil
		l.end = nil
		return
	}

	ptr := l.head
	for i := 0; i < idx-1; i++ {
		ptr = ptr.next
	}

	ptr.next = ptr.next.next
}

// Len 方法返回链表的长度
func (l *List[T]) Len() int {
	return l.len
}

// ToArray 方法用来返回一个存放所有链表元素的数组
func (l *List[T]) ToArray() []T {
	res := make([]T, 0, l.len)
	for ptr := l.head; ptr != nil; ptr = ptr.next {
		res = append(res, ptr.data)
	}
	return res
}
